package cn.icanci.ladybird.service.util.impl;

import cn.icanci.ladybird.common.result.JsonData;
import cn.icanci.ladybird.common.util.cache.RedisUtils;
import cn.icanci.ladybird.common.util.common.RandomValueUtils;
import cn.icanci.ladybird.common.util.security.SendEmailUtils;
import cn.icanci.ladybird.pojo.entity.UserInfo;
import cn.icanci.ladybird.service.UserInfoService;
import cn.icanci.ladybird.service.util.JavaMailByQqService;
import cn.icanci.ladybird.service.util.SendCodeService;
import cn.icanci.ladybird.service.util.SendSmsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import javax.mail.MessagingException;
import java.util.HashMap;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

/**
 * @author: icanci
 * @date: Created in 2020/10/14 14:57
 * @classAction: 统一发送Code的实现类
 */
@SuppressWarnings("all")
@Slf4j
@Service
public class SendCodeServiceImpl implements SendCodeService {

    @Autowired
    private RedisUtils redisUtils;
    @Autowired
    private SendSmsService sendSmsService;
    @Autowired
    private JavaMailByQqService javaMailByQqService;
    @Autowired
    private UserInfoService userInfoService;

    /**
     * 根据账户发送Code
     *
     * @param account    需要发送的数据 是Email、Phone
     * @param isRegister 是否是注册，1 是注册，0 不是注册
     * @return 返回JsonData对象
     */
    @Override
    public JsonData getCode(String account, String isRegister) throws MessagingException {
        if (null == account || account.trim().length() == 0) {
            return JsonData.builderError("参数有误，请输入正确的账号(邮箱或者手机号)");
        }
        // 正则表达式，判断手机号
        String regexPhone = "^((13[0-9])|(14[0,1,4-9])|(15[0-3,5-9])|(16[2,5,6,7])|(17[0-8])|(18[0-9])|(19[0-3,5-9]))\\d{8}$";
        Pattern compilePhone = Pattern.compile(regexPhone);
        Matcher matcherPhone = compilePhone.matcher(account);
        boolean matchesPhone = matcherPhone.matches();
        if (matchesPhone) {
            // 验证通过发送短信
            return sendSmsCode(account, isRegister);
        }
        // 正则表达式，判断邮箱
        String regexEmail = "^\\s*\\w+(?:\\.{0,1}[\\w-]+)*@[a-zA-Z0-9]+(?:[-.][a-zA-Z0-9]+)*\\.[a-zA-Z]+\\s*$";
        Pattern compileEmail = Pattern.compile(regexEmail);
        Matcher matcherEmail = compileEmail.matcher(account);
        boolean matchesEmail = matcherEmail.matches();
        if (matchesEmail) {
            // 发送邮件
            return sendEmailCode(account, isRegister);
        }
        return JsonData.builderError("手机格式或者邮箱格式错误");
    }

    /**
     * 存在-注册1
     * 不存在-注册1
     * 存在-登录0
     * 不存在-登录0
     */

    /**
     * 发送手机短信
     *
     * @param phone 手机号
     * @return 返回JsonData数据
     */
    private JsonData sendSmsCode(String phone, String isRegister) {
        UserInfo userInfo = userInfoService.queryOneByUsername(phone);
        // 存在-注册
        if (null != userInfo && "1".equals(isRegister)) {
            log.info("SendCodeServiceImpl.sendSmsCode - 手机用户已经注册，请登录");
            return JsonData.builderError("用户已经注册，请登录");
        } else if (null == userInfo && "1".equals(isRegister)) {
            // 不存在-注册
            // 调用方法发送
            return sendSmsCode(phone);
        } else if (null != userInfo && "0".equals(isRegister)) {
            // 存在-登录
            return sendSmsCode(phone);
        } else {
            // 不存在-登录。
            log.info("SendCodeServiceImpl.sendSmsCode - 手机用户不存在，请先注册");
            return JsonData.builderError("用户不存在，请先注册");
        }
    }

    /**
     * 短信登录
     *
     * @param phone 手机号
     * @return 返回JsonData对象
     */
    private JsonData sendSmsCode(String phone) {
        // 调用方法发送
        String code = String.valueOf(redisUtils.get(phone));
        log.info("手机验证码 code:" + code);
        log.info(String.valueOf("null".equals(code)));
        if (!"null".equals(code)) {
            // 已经存在，没有过期
            log.info("SendCodeServiceImpl.sendSmsCode - 验证码已经存在，请查看你的手机");
            return JsonData.builderError("验证码已经存在，请查看你的手机");
        }
        // 生成6位数验证码并且存储到Redis中
        code = String.valueOf(RandomValueUtils.getNum(100000, 999999));
        HashMap<String, Object> codeMap = new HashMap<>();
        codeMap.put("code", code);
        boolean isSend = sendSmsService.send(phone, "SMS_196653273", codeMap);
        if (isSend) {
            // 将手机号作为key,验证码作为 code，有效时间是5分钟
            redisUtils.set(phone, code, 5, TimeUnit.MINUTES);
            return JsonData.builderSuccess(null, "短信已经发送，5分钟之内有效，请注意查收");
        } else {
            log.info("SendCodeServiceImpl.sendSmsCode 网络异常");
            return JsonData.builderError("网络异常，发送失败");
        }
    }

    /**
     * 邮箱验证码登录
     *
     * @param email      邮箱
     * @param isRegister 是否是注册
     * @return 返回JsonData对象
     * @throws MessagingException
     */
    private JsonData sendEmailCode(String email, String isRegister) throws MessagingException {
        log.info("SendCodeServiceImpl.sendEmailCode - " + email + " - " + isRegister);
        UserInfo userInfo = userInfoService.queryOneByUsername(email);
        // 存在-注册
        if (null != userInfo && "1".equals(isRegister)) {
            log.info("SendCodeServiceImpl.sendEmailCode - Email用户不存在，请登录");
            return JsonData.builderError("用户已经注册，请登录");
        } else if (null == userInfo && "1".equals(isRegister)) {
            // 不存在-注册
            // 调用方法发送
            return sendEmailCode(email);
        } else if (null != userInfo && "0".equals(isRegister)) {
            // 存在-登录
            return sendEmailCode(email);
        } else {
            // 不存在-登录。
            log.info("SendCodeServiceImpl.sendEmailCode - Email用户不存在，请先注册");
            return JsonData.builderError("用户不存在，请先注册");
        }
    }

    /**
     * 邮箱登录验证码
     *
     * @param email 邮箱
     * @return 返回JsonData对象
     */
    private JsonData sendEmailCode(String email) {
        try {
            String targetCode = (String) redisUtils.get(email);
            if (!"null".equals(targetCode)) {
                String code = SendEmailUtils.getRandomEmailCode();
                javaMailByQqService
                        .sendMoreMail(
                                SendEmailUtils.LOGIN_SUBJECT,
                                SendEmailUtils.getManyMessage(code),
                                SendEmailUtils.FROM,
                                email
                        );
                // 设置到Reidis
                redisUtils.set(email, code, 5, TimeUnit.MINUTES);
                log.info("SendCodeServiceImpl.sendEmailCode - 邮件发送成功，请注意查收");
                return JsonData.builderSuccess(null, "邮件发送成功，请注意查收");
            } else {
                log.info("SendCodeServiceImpl.sendEmailCode - 验证码已经存在，请查看邮箱！");
                return JsonData.builderError("验证码已经存在，请查看邮箱！");
            }
        } catch (Exception e) {
            e.printStackTrace();
            log.info(e.getLocalizedMessage());
            log.info("SendCodeServiceImpl.sendEmailCode 网络异常");
            return JsonData.builderError("网络异常，请重试");
        }
    }
}
